﻿using DotNetty.Codecs.Http;
using DotNetty.Common.Concurrency;
using DotNetty.Transport.Bootstrapping;
using DotNetty.Transport.Channels;
using DotNetty.Transport.Channels.Sockets;
using JGSY.DotNetty.Common;
using JGSY.DotNetty.Server.Core;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;

namespace JGSY.DotNetty.Server.CoreImpl
{
    public class DotNettyServerImpl : IDotNettyServer
    {
        public event Action<string>? OnMessage;
        public event Action<string, string>? OnSubMessage;
        public event Action<Exception>? OnException;
        public event Func<string>? OnGetCommand;

        public async Task RunServerAsync()
        {
            OnSubMessage?.Invoke("服务启动中...", "重要");
            //第一步：创建ServerBootstrap实例
            // ServerBootstrap是Netty中用于启动服务端的辅助类，封装了服务器初始化的各种配置
            var bootstrap = new ServerBootstrap();
            // 第二步：绑定事件组（EventLoopGroup）
            // 创建主线程组（mainGroup），参数1表示使用1个线程，负责处理客户端连接的Accept操作
            IEventLoopGroup mainGroup = new MultithreadEventLoopGroup(1);
            // 创建工作线程组（workGroup），未指定线程数则使用默认值（通常为CPU核心数*2），负责处理连接后的IO操作（读写等）
            IEventLoopGroup workGroup = new MultithreadEventLoopGroup();
            // 将主线程组和工作线程组绑定到ServerBootstrap
            bootstrap.Group(mainGroup, workGroup);
            // 第三步：绑定服务端的通道类型
            // 指定服务端使用TcpServerSocketChannel，这是Netty中用于TCP协议的服务端通道实现
            bootstrap.Channel<TcpServerSocketChannel>();
            // 第四步：配置通道选项和处理器
            // 设置ChannelOption.SoBacklog=8192，表示TCP连接的等待队列大小（半连接队列）
            // 当服务器处理连接请求的速度小于客户端连接速度时，未处理的连接会暂时存在此队列中
            bootstrap.Option(ChannelOption.SoBacklog, 8192);

            // 配置子通道处理器（ChildHandler），用于处理每个新连接的初始化逻辑
            // ActionChannelInitializer是一个简化版的通道初始化器，当新连接建立时会执行传入的委托
            bootstrap.ChildHandler(new ActionChannelInitializer<IChannel>(channel =>
            {
                // 获取当前连接的通道流水线（Pipeline），流水线是Netty处理消息的核心，由一系列处理器（Handler）组成
                IChannelPipeline pipline = channel.Pipeline;

                // 向流水线添加HTTP编解码器（HttpServerCodec）
                // 作用：自动将字节流解码为HTTP请求对象，或将HTTP响应对象编码为字节流
                pipline.AddLast(new HttpServerCodec());

                // 添加HTTP对象聚合器（HttpObjectAggregator），参数65536表示最大聚合大小（64KB）
                // 作用：将HTTP请求的多个部分（如请求头、请求体）聚合为一个完整的IFullHttpRequest对象，方便后续处理
                pipline.AddLast(new HttpObjectAggregator(65536));

                // 添加自定义的业务处理器（ChannelHandler），用于处理聚合后的HTTP请求并返回响应
                // 这里使用的就是你之前提到的ChannelHandler类 ApplicationService.GetService<ChannelHandler>()
                //pipline.AddLast(new ChannelHandler());  优化 DI
                var handler = ApplicationService.GetService<ChannelHandler>();
                if (OnException != null)
                {
                    handler.OnException += OnException;
                }
                pipline.AddLast(handler);
            }));

            // 第五步：配置并绑定服务器的主机地址和端口号
            IPAddress iPAddress = GetTrueIPAddress();

            // 异步绑定服务器到指定的IP地址和端口（端口从配置文件获取），返回绑定后的通道对象
            // 这一步是启动服务器的关键操作，执行后服务器开始监听指定端口的连接请求
            IChannel bootStrapChannel = await bootstrap.BindAsync(iPAddress, ApplicationConfig.ServerConfig.Port);



            //0、这段代码通过 Netty 框架的 ServerBootstrap 构建了一个 TCP 服务器，主要流程是：
            //1、初始化服务器启动器（ServerBootstrap）
            //2、配置处理连接的线程模型（主线程组负责接收连接，工作线程组负责处理 IO）
            //3、指定 TCP 协议的通道类型
            //4、配置通道参数（如连接队列大小）和消息处理流水线（添加 HTTP 编解码、聚合器和自定义业务处理器）
            //5、绑定到具体的 IP 地址和端口，启动服务器监听连接





            OnSubMessage?.Invoke("服务启动成功", "重要");
            OnMessage?.Invoke($"已监听http://{iPAddress}:{ApplicationConfig.ServerConfig.Port}");
            //第六步：停止服务
            OnMessage?.Invoke("输入Stop停止服务");
            WaitServerStop();
            OnSubMessage?.Invoke("正在停止服务", "重要");
            await bootStrapChannel.CloseAsync();
            OnSubMessage?.Invoke("服务已停止", "重要");




            //await Task.Run(() => {

            //    OnSubMessage?.Invoke("服务启动成功！", "重要");
            //    OnMessage?.Invoke("输入Stop停止服务");
            //    string? inputKey = string.Empty;
            //    while(!string.Equals(inputKey,"Stop",StringComparison.Ordinal)){

            //        inputKey = OnGetCommand?.Invoke();
            //        if (!string.Equals(inputKey, "Stop", StringComparison.Ordinal))
            //        {
            //            OnException?.Invoke(new DotNettyServerException("未识别命令请重新输入"));
            //        }
            //    }
            //    OnSubMessage?.Invoke("正在停止服务", "重要");
            //    OnSubMessage?.Invoke("服务已停止", "重要");


            //});
        }

        private static IPAddress GetTrueIPAddress()
        {
            // 获取当前主机名
            string hostName = Dns.GetHostName();
            // 根据主机名获取所有绑定的IP地址（可能包含IPv4和IPv6）
            IPAddress[] iPAddresses = Dns.GetHostAddresses(hostName);
            // 筛选出IPv4地址（假设IsIPv4()是一个扩展方法，用于判断是否为IPv4地址）
            iPAddresses = iPAddresses.Where(m => m.ToString().IsIPv4()).ToArray();

            // 检查配置文件中指定的主机地址（ApplicationConfig.ServerConfig.Host）是否在本机IP中存在
            bool trueAddress = iPAddresses.Any(m => ApplicationConfig.ServerConfig.Host.Equals(m.ToString()));
            // 如果存在则使用配置的IP，否则使用第一个可用的IPv4地址
            IPAddress iPAddress = trueAddress ? IPAddress.Parse(ApplicationConfig.ServerConfig.Host) : iPAddresses[0];
            return iPAddress;
        }

        private void WaitServerStop()
        {
            string? inputKey = string.Empty;
            while (!string.Equals(inputKey, "Stop", StringComparison.Ordinal))
            {
                inputKey = OnGetCommand?.Invoke();
                if (!string.Equals(inputKey, "Stop", StringComparison.Ordinal))
                {
                    OnException?.Invoke(new DotNettyServerException("未识别命令请重新输入"));
                }
            }
        }
    }
}
